package com.stox.core.ui.swing.wrapper;

import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragSource;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;
import java.util.Vector;

import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;

import org.jdesktop.swingx.JXTree;

import com.stox.core.ui.swing.util.SwingUtil;
import com.stox.core.ui.swing.widget.ListTransferable;

public class JTree extends JXTree implements DragGestureListener{
	private static final long serialVersionUID = 5622318116250346150L;

	public void init(){
		SwingUtil.initializeWidget(this);
		DragSource ds = new DragSource();
	    ds.createDefaultDragGestureRecognizer(this,
	            DnDConstants.ACTION_COPY, this);
	}
	
	@Override
	public void dragGestureRecognized(DragGestureEvent event) {
		 if (event.getDragAction() == DnDConstants.ACTION_COPY) {
			 event.startDrag(null, new ListTransferable(getSelectedLeafUserObjects()));
		 }	
	}
	
	public void selectAndShow(TreeNode node){
		selectAndShow(new TreePath(((DefaultTreeModel)getModel()).getPathToRoot(node)));
	}
	
	public void selectAndShow(TreePath path){
		setSelectionPath(path);
		expandPath(path);
		scrollPathToVisible(path);
	}
	
	public JTree() {
		super();
		init();
	}

	public JTree(Hashtable<?, ?> value) {
		super(value);
		init();
	}

	public JTree(Object[] value) {
		super(value);
		init();
	}

	public JTree(TreeModel newModel) {
		super(newModel);
		init();
	}

	public JTree(TreeNode root, boolean asksAllowsChildren) {
		super(root, asksAllowsChildren);
		init();
	}

	public JTree(TreeNode root) {
		super(root);
		init();
	}

	public JTree(Vector<?> value) {
		super(value);
		init();
	}
	
	public void expandNode(TreePath parent) {
	TreeNode node = (TreeNode)parent.getLastPathComponent();
		if (node.getChildCount() >= 0) {
		Enumeration<?> e = node.children();
		while(e.hasMoreElements()) {
			TreeNode n = (TreeNode)e.nextElement();
			TreePath path = parent.pathByAddingChild(n);
			expandNode(path);
		}
		}
		expandPath(parent);
	}
	
	@SuppressWarnings("rawtypes")
	public boolean containsChildWithUserObject(Object object, DefaultMutableTreeNode node){
		if(node.getUserObject().equals(object)){
			return true;
		}
		if(!node.isLeaf()){
			Enumeration children = node.children();
			while(children.hasMoreElements()){
				DefaultMutableTreeNode child = (DefaultMutableTreeNode)children.nextElement();
				if(containsChildWithUserObject(object, child)){
					return true;
				}
			}
		}
		return false;
	}
	
	public List<?> getSelectedLeafUserObjects(){
		List<Object> list = new ArrayList<Object>();
		TreePath[] paths = getSelectionPaths();
		if(paths != null && paths.length != 0){
			for(TreePath path : paths){
				if(path != null){
					DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent();
					List<?> otherList = getSelectedLeafUserObjects(node);
					if(otherList != null && !otherList.isEmpty()){
						for(Object object : otherList){
							if(!list.contains(object)){
								list.add(object);
							}
						}
					}
				}
			}
		}
		return list;
	}
	
	public List<?> getSelectedLeafUserObjects(DefaultMutableTreeNode node){
		List<Object> list = new ArrayList<Object>();
		if(node.isLeaf()){
			list.add(node.getUserObject());
		}else{
			Enumeration<?> children = node.children();
			while(children.hasMoreElements()){
				List<?> otherList = getSelectedLeafUserObjects((DefaultMutableTreeNode)children.nextElement());
				if(otherList != null && !otherList.isEmpty()){
					for(Object object : otherList){
						if(!list.contains(object)){
							list.add(object);
						}
					}
				}
			}
		}
		return list;
	}
	
}